/**
 * 全局管理器 - 电路网络管理
 */
import type { IPin, ICircuitElement, IHitTestable, IHitTester, HitTestResult, IWire } from './circuit-elements.js';

export class GlobalManager {
  private static instance: GlobalManager;
  private nets: Map<string, Set<IPin>> = new Map();
  private elements: Map<string, ICircuitElement> = new Map(); // 全局元件存储
  private wires: Map<string, IWire> = new Map(); // Wire连接存储
  private pins: Map<string, IPin> = new Map(); // Pin全局索引
  
  private constructor() {}

  public static getInstance(): GlobalManager {
    if (!GlobalManager.instance) {
      GlobalManager.instance = new GlobalManager();
    }
    return GlobalManager.instance;
  }

  /**
   * 创建新网络
   * 来自接口：ICircuitElement
   */
  createNet(pin: IPin): string {
    const netId = `net_${Date.now()}`;
    this.nets.set(netId, new Set([pin]));
    pin.connectionNetId = netId;
    return netId;
  }

  /**
   * 合并两个网络
   */
  mergeNets(netId1: string, netId2: string): string {
    const net1 = this.nets.get(netId1);
    const net2 = this.nets.get(netId2);
    
    if (!net1 || !net2) return netId1;

    const mergedNet = new Set([...net1, ...net2]);
    this.nets.set(netId1, mergedNet);
    this.nets.delete(netId2);
    
    // 更新所有pin的网络引用
    mergedNet.forEach(pin => {
      pin.netId = netId1;
    });

    return netId1;
  }

  /**
   * 获取网络中的所有pin
   */
  getNetPins(netId: string): IPin[] {
    return Array.from(this.nets.get(netId) || []);
  }

  /**
   * 电路仿真 - 基尔霍夫定律计算
   * 来自接口：ICircuitElement
   */
  simulate(): void {
    // 1. 收集所有独立网络
    const independentNets = this.getIndependentNets();
    
    // 2. 为每个网络列写KCL方程
    independentNets.forEach(net => {
      const pins = this.getNetPins(net);
      const currents = pins.map(pin => pin.current);
      const sumCurrent = currents.reduce((sum, curr) => sum + curr, 0);
      
      // 确保KCL成立：ΣI = 0
      if (Math.abs(sumCurrent) > 1e-6) {
        this.adjustCurrents(pins, sumCurrent);
      }
    });
  }

  private getIndependentNets(): string[] {
    const visited = new Set<string>();
    const independentNets: string[] = [];
    
    for (const [netId] of this.nets) {
      if (!visited.has(netId)) {
        independentNets.push(netId);
        visited.add(netId);
      }
    }
    
    return independentNets;
  }

  private adjustCurrents(pins: IPin[], delta: number): void {
    const adjustment = -delta / pins.length;
    pins.forEach(pin => {
      pin.current += adjustment;
    });
  }

  /**
   * 注册元件到全局管理器
   * @param element 要注册的元件实例
   */
  registerElement(element: ICircuitElement): void {
    this.elements.set(element.id, element);
    
    // 同时注册所有Pin到全局索引
    element.pins.forEach(pin => {
      this.pins.set(pin.id, pin);
    });
  }

  /**
   * 从全局管理器注销元件
   * @param id 要注销的元件ID
   */
  unregisterElement(id: string): void {
    this.elements.delete(id);
  }

  /**
   * 根据元件ID获取元件实例
   * @param id 要查找的元件ID
   * @returns 找到的元件实例，如果未找到则返回undefined
   */
  getElementById(id: string): ICircuitElement | undefined {
    return this.elements.get(id);
  }

  /**
   * 获取所有已注册的元件
   * @returns 所有元件实例的数组
   */
  getAllElements(): ICircuitElement[] {
    return Array.from(this.elements.values());
  }

  /**
   * 注册Wire到全局管理器
   * @param wire 要注册的Wire实例
   */
  registerWire(wire: IWire): void {
    this.wires.set(wire.id, wire);
    
    // 自动更新网络：将连接的Pin添加到相同网络
    this.updateWireNetwork(wire);
  }

  /**
   * 注销Wire
   * @param wireId 要注销的Wire ID
   */
  unregisterWire(wireId: string): void {
    const wire = this.wires.get(wireId);
    if (wire) {
      // 分离网络连接
      this.separateWireNetwork(wire);
      this.wires.delete(wireId);
    }
  }

  /**
   * 根据Wire ID获取Wire实例
   * @param wireId 要查找的Wire ID
   * @returns 找到的Wire实例，如果未找到则返回undefined
   */
  getWireById(wireId: string): IWire | undefined {
    return this.wires.get(wireId);
  }

  /**
   * 根据Pin ID获取Pin实例
   * @param pinId 要查找的Pin ID
   * @returns 找到的Pin实例，如果未找到则返回undefined
   */
  getPinById(pinId: string): IPin | undefined {
    return this.pins.get(pinId);
  }

  /**
   * 获取所有已注册的Wire
   * @returns 所有Wire实例的数组
   */
  getAllWires(): IWire[] {
    return Array.from(this.wires.values());
  }

  /**
   * 清除所有元件和网络
   */
  clearAll(): void {
    this.elements.clear();
    this.wires.clear();
    this.pins.clear();
    this.nets.clear();
  }

  // 私有方法：网络管理

  /**
   * 更新Wire连接的网络
   */
  private updateWireNetwork(wire: IWire): void {
    const { startPin, endPin } = wire.getConnectedPins();
    
    if (!startPin || !endPin) return;

    // 如果两个Pin都没有网络，创建新网络
    if (!startPin.connectionNetId && !endPin.connectionNetId) {
      const netId = this.createNet(startPin);
      endPin.connectionNetId = netId;
      this.nets.get(netId)?.add(endPin);
    } 
    // 如果只有一个Pin有网络，将另一个Pin加入该网络
    else if (startPin.connectionNetId && !endPin.connectionNetId) {
      endPin.connectionNetId = startPin.connectionNetId;
      this.nets.get(startPin.connectionNetId)?.add(endPin);
    } 
    else if (!startPin.connectionNetId && endPin.connectionNetId) {
      startPin.connectionNetId = endPin.connectionNetId;
      this.nets.get(endPin.connectionNetId)?.add(startPin);
    } 
    // 如果两个Pin都有不同网络，合并网络
    else if (startPin.connectionNetId !== endPin.connectionNetId) {
      this.mergeNets(startPin.connectionNetId!, endPin.connectionNetId!);
    }
  }

  /**
   * 分离Wire连接的网络
   */
  private separateWireNetwork(wire: IWire): void {
    const { startPin, endPin } = wire.getConnectedPins();
    
    if (!startPin || !endPin) return;

    // 简单处理：将两个Pin的网络设为null
    // 在实际应用中，可能需要更复杂的网络重算逻辑
    const netId = startPin.connectionNetId || endPin.connectionNetId;
    if (netId) {
      const net = this.nets.get(netId);
      if (net) {
        net.delete(startPin);
        net.delete(endPin);
        
        // 如果网络为空，删除该网络
        if (net.size === 0) {
          this.nets.delete(netId);
        }
      }
    }
    
    startPin.connectionNetId = null;
    endPin.connectionNetId = null;
  }
}

export const editorTokenManager = {
    createToken: (editorId: string) => ({
        id: `token_${Date.now()}`,
        editorId,
        permissions: {
            canEditElements: true,
            canModifyPins: true
        },
        validUntil: Date.now() + 3600000 // 1 hour
    }),
    verifyToken: (tokenId: string) => {
        // 简化验证逻辑
        return tokenId.startsWith('token_');
    }
};

// 将视口长度转换为SVG长度
export function viewportLengthToSVG(xlen: number, ylen: number, ctm: DOMMatrix): DOMPoint{
    return new DOMPoint(xlen / ctm.a, ylen / ctm.d);  // ctm.a 是X轴的缩放因子
}

/**
 * 拖拽相关工具函数
 */
export const dragManager = {
    /**
     * 初始化元素拖拽
     */
    setupDrag: (element: HTMLElement, toolType: string) => {
        element.draggable = true;
        
        element.addEventListener('dragstart', (e) => {
            e.dataTransfer?.setData('application/x-circuit-tool', toolType);
            element.style.opacity = '0.4';
        });

        element.addEventListener('dragend', () => {
            element.style.opacity = '1';
        });
    },

    /**
     * 初始化拖放区域
     */
    setupDrop: (element: SVGSVGElement, callback: (toolType: string, x: number, y: number) => void) => {
        element.addEventListener('dragover', (e) => {
            e.preventDefault();
        });

        element.addEventListener('drop', (e) => {
            e.preventDefault();
            const toolType = e.dataTransfer?.getData('application/x-circuit-tool');
            if (toolType) {
                // 直接传递屏幕坐标，让CanvasManager处理完整的坐标转换
                callback(toolType, e.clientX, e.clientY);
            }
        });
    },

    /**
     * 初始化元件拖动功能
     */
    setupElementDrag: (element: SVGGElement, onDrag: (dx: number, dy: number) => void) => {
        let isDragging = false;
        let startx = 0, starty = 0;

        element.addEventListener('mousedown', (e) => {
            const target = e.target as SVGElement;
            if (target.closest('circle[data-pin-id]')) {
                // 如果是引脚点击，不启动拖动
                return;
            }

            isDragging = true;
            startx = e.clientX;
            starty = e.clientY;
            element.style.cursor = 'grabbing';
            e.stopPropagation();
        });

        document.addEventListener('mousemove', (e) => {
            if (!isDragging) return;
            const dx = e.clientX - startx;
            const dy = e.clientY - starty;
            const svgElement = element.closest('svg');
            const svgLen = viewportLengthToSVG(dx, dy, svgElement!.getScreenCTM()!);
            onDrag(svgLen.x, svgLen.y);
            startx = e.clientX;
            starty = e.clientY;
        });

        document.addEventListener('mouseup', () => {
            if (isDragging) {
                isDragging = false;
                element.style.cursor = '';
            }
        });
    },


};

/**
 * 场景命中测试器的实现
 */
export class SceneHitTester implements IHitTester {
  private hitTestables: Set<IHitTestable> = new Set();

  register(hitTestable: IHitTestable): void {
    this.hitTestables.add(hitTestable);
  }

  unregister(hitTestable: IHitTestable): void {
    this.hitTestables.delete(hitTestable);
  }

  hitTestAll(point: { x: number; y: number }, tolerance: number = 5): HitTestResult[] {
    const results: HitTestResult[] = [];

    for (const obj of this.hitTestables) {
      const result = obj.hitTest(point, tolerance);
      if (result && result.isHit) {
        results.push(result);
      }
    }

    // 按距离从小到大排序，最近的（最上层的）对象在前
    results.sort((a, b) => a.distanceSquared - b.distanceSquared);
    return results;
  }

  hitTestFirst(point: { x: number; y: number }, tolerance: number = 5): HitTestResult | null {
    const allHits = this.hitTestAll(point, tolerance);
    return allHits.length > 0 ? allHits[0] : null;
  }
}

export const sceneHitTester = new SceneHitTester();
export const globalMgr = GlobalManager.getInstance();